#include "RB-Tree.h"
#include "Set.h"
#include "Map.h"
#include "Pair.h"

#include <functional>

template <typename T>
struct identity
{
    constexpr T &&operator()(T &&t) const noexcept
    {
        return std::forward<T>(t);
    }

    constexpr const T &operator()(const T &t) const noexcept
    {
        return t;
    }

    T &&operator()(T &&t)
    {
        return std::forward<T>(t);
    }
};

int main()
{
    using int_rb_tree = rb_tree<int, int, identity<int>, std::less<int>>;
    rb_tree<int, int, identity<int>, std::less<int>> rbTree;
    rbTree.insert_unique(10);
    rbTree.insert_unique(7);
    rbTree.insert_unique(8);
    rbTree.insert_unique(15);
    rbTree.insert_unique(6);
    rbTree.insert_unique(11);
    rbTree.insert_unique(13);
    rbTree.insert_unique(12);
    rbTree.insert_equal(15);

    auto iter = rbTree.find(10);

    using link_type = int_rb_tree::link_type;

    std::cout << "before erase size : " << rbTree.size() << std::endl;

    std::cout << "Traverse Tree Before Erase" << std::endl;

    for (
        int_rb_tree::iterator iter1 = rbTree.begin(),
                              iter2 = rbTree.end();
        iter1 != iter2; iter1++)
    {
        std::cout << *iter1 << std::endl;
    }

    rbTree.erase(iter);

    std::cout << "After erase size : " << rbTree.size() << std::endl;

    std::cout << "Traverse Tree After Erase" << std::endl;

    for (
        int_rb_tree::iterator iter1 = rbTree.begin(),
                              iter2 = rbTree.end();
        iter1 != iter2; iter1++)
    {
        std::cout << *iter1 << std::endl;
    }

    std::cout << "Test value delete 15" << std::endl;

    rbTree.erase(15);

    std::cout << "After erase size : " << rbTree.size() << std::endl;

    std::cout << "Traverse Tree After Erase" << std::endl;

    for (
        int_rb_tree::iterator iter1 = rbTree.begin(),
                              iter2 = rbTree.end();
        iter1 != iter2; iter1++)
    {
        std::cout << *iter1 << std::endl;
    }

    // test set

    std::cout << "Test Set" << std::endl;

    int ele[] = {1, 2, 3, 4, 5};
    set<int> Set(ele, ele + 5);
    std::cout << Set.size() << std::endl;

    Set.insert(3);
    std::cout << Set.size() << std::endl;

    Set.insert(6);
    std::cout << Set.size() << std::endl;

    Set.erase(3);
    std::cout << Set.size() << std::endl;

    auto begin = Set.begin();
    auto end = Set.end();

    for(; begin != end; begin ++)
        std::cout << *begin << " ";
    std::cout <<  std::endl;

    // testing map
    map<std::string, int> myMap;
    // insert
    myMap[std::string("jj")] = 1;
    myMap[std::string("je")] = 2;
    myMap[std::string("ja")] = 3;
    myMap[std::string("ji")] = 4;

    hamster::pair<const std::string, int> value = hamster::make_pair<const std::string, int>(std::string("da"), 5);
    auto res = myMap.insert(value);

    auto map_iter = myMap.begin();
    for(; map_iter != myMap.end(); map_iter ++)
    {
        std::cout << map_iter->first << " " << map_iter->second << std::endl;
    }

    // get value 
    int number = myMap[std::string("jj")];
    std::cout << "jj number is " << number << std::endl;
}